package hos.thread

import android.util.Log
import hos.thread.executor.TS

/**
 * <p>Title: RunJob </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2023/8/4 21:03
 * @version : 1.0
 */
@Suppress("UNCHECKED_CAST")
open class RunnableJob<T> protected constructor(
    protected open val onBackground: (RunnableJob<T>.() -> T),
) : RunnableLife() {

    companion object {

        @JvmStatic
        @JvmOverloads
        fun <T> run(
            job: ThreadOption.Job = ThreadOption.Job.ON,
            onBackground: (RunnableJob<T>.() -> T),
        ) = RunnableJob<T>(onBackground).start(job)

        @JvmStatic
        fun <T> get(
            onBackground: (RunnableJob<T>.() -> T),
        ) = RunnableJob<T>(onBackground)

    }

    @JvmOverloads
    open fun start(
        job: ThreadOption.Job = ThreadOption.Job.ON,
    ): RunnableJob<T> {
        if (isRunning()) {
            return this
        }
        reset()
        if (job == ThreadOption.Job.TO) {
            TS.postIo(this)
            return this
        }
        TS.postOnIo(this)
        return this
    }

    protected var onSuccess: (RunnableJob<T>.(T?) -> Unit)? = null

    open fun onSuccess(success: (RunnableJob<T>.(T?) -> Unit)): RunnableJob<T> {
        this.onSuccess = success
        return this
    }

    override fun progressUpdate(value: Double) {
        postProgress(value)
    }

    override fun setStatusListener(listener: RunnableLife.(ThreadOption.Status) -> Unit): RunnableJob<T> {
        return super.setStatusListener(listener) as RunnableJob<T>
    }

    override fun onStart(start: RunnableLife.(String) -> Unit): RunnableJob<T> {
        return super.onStart(start) as RunnableJob<T>
    }

    override fun onProgress(progress: Double.() -> Unit): RunnableJob<T> {
        return super.onProgress(progress) as RunnableJob<T>
    }

    override fun onCatch(throwable: Throwable.(String) -> Unit): RunnableJob<T> {
        return super.onCatch(throwable) as RunnableJob<T>
    }

    override fun onCancel(onCancel: String.() -> Unit): RunnableJob<T> {
        return super.onCancel(onCancel) as RunnableJob<T>
    }

    override fun run(run: RunnableThis) {
        val currentThread = Thread.currentThread()
        try {
            currentThread.setUncaughtExceptionHandler { t, e ->
                postThrowable(e)
            }
            if (isCancel()) {
                // 取消
                postCancel()
                return
            }
            postStart()
            // 运行
            val result = runBackground()
            if (isCancel() && isStatus(ThreadOption.Status.ON_DESTROY)) {
                // 已经取消，并且被销毁了，说明当前页面
                Log.d("Thread", "run: onCancel && onDestroy")
                return
            }
            Log.d("Thread", "run: onBackgroundSuccess")
            if (isCancel()) {
                // 取消
                postCancel()
                return
            }
            postResult(result)
        } catch (e: Throwable) {
            postThrowable(e)
        } finally {
            //移除所有消息.防止需要执行onCompleted了，onPrepare还没被执行，那就不需要执行了
//            MH.getHandler().removeCallbacksAndMessages(null);
            changedStatus(ThreadOption.Status.ON_DESTROY)
        }
    }

    /**
     * 结果处理
     */
    @Throws(Throwable::class)
    protected open fun runBackground(): T {
        Log.d("Thread", "run: onBackground")
        changedStatus(ThreadOption.Status.ON_RUNNING)
        return onBackground.invoke(this)
    }

    /**
     * 结果处理
     */
    protected open fun postResult(result: T?) {
        runUI {
            try {
                // 执行完成
                Log.d("Thread", "run: onSuccess")
                onSuccess?.invoke(this@RunnableJob, result)
                changedStatus(ThreadOption.Status.ON_SUCCESS)
            } catch (e: Throwable) {
                // 异常
                postThrowable(e)
            }
        }
    }


    override fun onDestroy() {
        super.onDestroy()
        onSuccess = null
    }
}